//
//
#include "Stdafx.h"
#include "Algorithm2D.h"


namespace Geometric
{
	int Algorithm2D::getIntersectPoint( Line2D& _line1, Line2D& _line2, Point2D& _point )
	{
		double base = _line1.m_a*_line2.m_b - _line1.m_b*_line2.m_a;

		if(Gmath::isZero(base) == false)
		{
			_point.m_x = (_line1.m_b*_line2.m_c - _line1.m_c*_line2.m_b) / base;
			_point.m_y = (_line1.m_c*_line2.m_a - _line1.m_a*_line2.m_c) / base;
			return LINE_LINE_INTERSECT;
		}
		else
		{
			return (_line1.isOverlap(_line2) == true 
				? LINE_LINE_OVERLAP : LINE_LINE_PARALLEL);
		}
	}

	int Algorithm2D::getIntersectPoint( Ray2D& _ray1, Ray2D& _ray2, Point2D& _point )
	{
		Line2D line2D_1(_ray1.m_point, _ray1.m_vector);
		Line2D line2D_2(_ray2.m_point, _ray2.m_vector);
		Point2D new_point;

		int code = getIntersectPoint(line2D_1, line2D_2, new_point);
		if(code == LINE_LINE_INTERSECT)
		{
			if(_ray1.isPointOnRay(new_point) && _ray2.isPointOnRay(new_point))
			{
				_point = new_point;
				return RAY_RAY_INTERSECT;
			}
		}
		else if(code == LINE_LINE_PARALLEL)
		{
			if(_ray1.isSameDirection(_ray2) == true)
				return RAY_RAY_SAME_PARALLEL;
			else return RAY_RAY_OPP_PARALLEL;
		}
		else if(code == LINE_LINE_OVERLAP)
		{
			if(_ray1.isSameDirection(_ray2) == false)
			{
				if(_ray1.m_point == _ray2.m_point)
				{
					_point = _ray1.m_point;
					return RAY_RAY_INTERSECT;
				}
				else if(_ray1.isPointOnRay(_ray2.m_point))
				{
					_point = _ray1.m_point;
					return RAY_RAY_OVERLAP;
				}
				else return RAY_RAY_NOT_INTERSECT;
			}
			else
			{
				return RAY_RAY_OVERLAP;
			}
		}

		return RAY_RAY_NOT_INTERSECT;
	}

	int Algorithm2D::getIntersectPoint( Segment2D& _segment1, Segment2D& _segment2, Point2D& _point )
	{
		Line2D line1(_segment1.m_start, _segment1.m_end);
		Line2D line2(_segment2.m_start, _segment2.m_end);
		Point2D new_point;

		int code = getIntersectPoint(line1, line2, new_point);
		if(code == LINE_LINE_INTERSECT)
		{
			if(_segment1.isInRect(new_point) && _segment2.isInRect(new_point))
			{
				_point = new_point;
				return SEG_SEG_INTERSECT;
			}
		}
		else if(code == LINE_LINE_OVERLAP)
		{
			double max1 = Gmath::toMax(_segment1.m_start.m_x, _segment1.m_end.m_x);
			double min1 = Gmath::toMin(_segment1.m_start.m_x, _segment1.m_end.m_x);

			double max2 = Gmath::toMax(_segment2.m_start.m_x, _segment2.m_end.m_x);
			double min2 = Gmath::toMin(_segment2.m_start.m_x, _segment2.m_end.m_x);

			if(Gmath::isEqual(min1, max2) || Gmath::isEqual(max1, min2))
			{
				if(_segment1.m_start == _segment2.m_start
					|| _segment1.m_start == _segment2.m_end)
					_point = _segment1.m_start;
				else _point = _segment1.m_end;

				return SEG_SEG_INTERSECT;
			}
			else if(Gmath::isLess(min1, max2) && Gmath::isEqual(min2, max1))
			{
				return SEG_SEG_OVERLAP;
			}
		}
		else if(code == LINE_LINE_PARALLEL)
		{
			return SEG_SEG_PARALLEL;
		}

		return SEG_SEG_NOT_INTERSECT;
	}

	int Algorithm2D::getIntersectPoint( Line2D& _line, Segment2D& _segment, Point2D& _point )
	{
		Line2D new_line(_segment.m_start, _segment.m_end);
		Point2D new_point;

		int code = getIntersectPoint(_line, new_line, new_point);
		if(code == LINE_LINE_INTERSECT)
		{
			if(_segment.isInRect(new_point) == true)
			{
				_point = new_point;
				return LINE_SEG_INTERSECT;
			}
		}
		else if(code == LINE_LINE_PARALLEL) 
		{
			return LINE_SEG_PARALLEL;
		}
		else if(code == LINE_LINE_OVERLAP)
		{
			return LINE_SEG_OVERLAP;
		}

		return LINE_SEG_NOT_INTERSECT;
	}

	int Algorithm2D::getIntersectPoint( Line2D& _line, Ray2D _ray, Point2D& _point )
	{
		Line2D new_line(_ray.m_point, _ray.m_vector);
		Point2D new_point;

		int code = getIntersectPoint(_line, new_line, new_point);
		if(code == LINE_LINE_INTERSECT)
		{
			if(_ray.isPointOnRay(new_point) == true)
			{
				_point = new_point;
				return LINE_RAY_INTERSECT;
			}
			else return LINE_RAY_NOT_INTERSECT;
		}
		else if(code == LINE_LINE_PARALLEL)
		{
			return LINE_RAY_PARALLEL;
		}
		else if(code == LINE_LINE_OVERLAP)
		{
			return LINE_RAY_OVERLAP;
		}

		return LINE_RAY_NOT_INTERSECT;
	}

	int Algorithm2D::getIntersectPoint( Segment2D& _segment, Ray2D& _ray, Point2D& _point )
	{
		Line2D line1(_segment.m_start, _segment.m_end);
		Line2D line2(_ray.m_point, _ray.m_vector);
		Point2D new_point;

		int code = getIntersectPoint(line1, line2, new_point);
		if(code == LINE_LINE_INTERSECT)
		{
			if(_segment.isOnSegment(new_point) && _ray.isPointOnRay(new_point))
			{
				_point = new_point;
				return SEG_RAY_INTERSECT;
			}
		}
		else if(code == LINE_LINE_PARALLEL)
		{
			return SEG_RAY_PARALLEL;
		}
		else if(code == LINE_LINE_OVERLAP)
		{
			bool s_flag = _ray.isPointOnRay(_segment.m_start);
			bool e_flag = _ray.isPointOnRay(_segment.m_end);

			if(s_flag == true && e_flag == true)
			{
				return SEG_RAY_OVERLAP;
			}
			else if(s_flag == true)
			{
				if(_segment.m_start == _ray.m_point)
				{
					_point = _segment.m_start;
					return SEG_RAY_INTERSECT;
				}
				else return SEG_RAY_OVERLAP;
			}
			else if(e_flag == true)
			{
				if(_segment.m_end == _ray.m_point)
				{
					_point = _segment.m_end;
					return SEG_RAY_INTERSECT;
				}
				else return SEG_RAY_OVERLAP;
			}

			return SEG_RAY_SAME_PARALLEL;
		}

		return SEG_RAY_NOT_INTERSECT;
	}

	bool Algorithm2D::isInside( Circle& _circle, Rectangle2D& _rect )
	{
		Line2D line(_rect.getA(), _rect.getB());
		double dis = 0;

		dis = line.getDistance(_circle.getOrigin());
		if(Gmath::isLessAndEqual(dis, _circle.getRadius()) == false)
		{
			return false;
		}

		line.set(_rect.getB(), _rect.getC());
		dis = line.getDistance(_circle.getOrigin());
		if(Gmath::isLessAndEqual(dis, _circle.getRadius()) == false)
		{
			return false;
		}

		line.set(_rect.getC(), _rect.getD());
		dis = line.getDistance(_circle.getOrigin());
		if(Gmath::isLessAndEqual(dis, _circle.getRadius()) == false)
		{
			return false;
		}

		line.set(_rect.getD(), _rect.getA());
		dis = line.getDistance(_circle.getOrigin());
		if(Gmath::isLessAndEqual(dis, _circle.getRadius()) == false)
		{
			return false;
		}

		return true;
	}

}

